home *** CD-ROM | disk | FTP | other *** search
/ Aminet 35 / Aminet 35 (2000)(Schatztruhe)[!][Feb 2000].iso / Aminet / game / shoot / ADescentSrc.lha / descent / Amiga / Warp3D.c < prev    next >
C/C++ Source or Header  |  1999-04-05  |  40KB  |  1,648 lines

  1. /*
  2.  * $Source: /usr/CVS/descent/Amiga/Warp3D.c,v $
  3.  * $Author: nobody $
  4.  * $Date: 1999/03/10 23:26:42 $
  5.  * $Revision: 1.4 $
  6.  *
  7.  * Warp3D stuff for Descent
  8.  *
  9.  * $Log: Warp3D.c,v $
  10.  * Revision 1.4  1999/03/10 23:26:42  nobody
  11.  * Warp3D V2 adaption
  12.  *
  13.  * Revision 1.3  1998/12/21 17:12:20  nobody
  14.  * *** empty log message ***
  15.  *
  16.  * Revision 1.2  1998/11/09 22:20:17  nobody
  17.  * *** empty log message ***
  18.  *
  19.  * Revision 1.1  1998/09/26 15:16:01  nobody
  20.  * Initial version
  21.  *
  22.  *
  23.  *
  24.  */
  25. #ifdef WARP3D
  26.  
  27. #include <Warp3D/Warp3D.h>
  28. #include <cybergraphics/cybergraphics.h>
  29. #include <intuition/intuition.h>
  30. #include <exec/exec.h>
  31. #include <graphics/gfx.h>
  32. #include <libraries/asl.h>
  33.  
  34. #include <clib/Warp3D_protos.h>
  35. #include <inline/Warp3D.h>
  36. #include <clib/cybergraphics_protos.h>
  37. #include <inline/cybergraphics.h>
  38. #include <clib/exec_protos.h>
  39. #include <inline/exec.h>
  40.  
  41. #include "types.h"
  42. #include "mem.h"
  43. #include "gr.h"
  44. #include "grdef.h"
  45. #include "error.h"
  46. #include "mono.h"
  47. #include "palette.h"
  48. #include "args.h"
  49. #include "timer.h"
  50. #include "rle.h"
  51. #include "gauges.h"
  52. #include "texmap.h"
  53. #include "3d.h"
  54. #include "iff.h"
  55. #include "object.h"
  56.  
  57. #include <stdio.h>
  58.  
  59. #define debug(x) //printf x
  60. #define PROF_CACHE 0
  61.  
  62. extern struct Library *Warp3DBase;
  63. extern struct Library *SysBase;
  64.  
  65. extern int gr_keep_resolution;
  66. #define WARP_GetBufferAddress() (void *)(WARP_Buffers[1-WARP_Buffer])
  67.  
  68. //  Misc stuff
  69. W3D_Context *WARP_Context = NULL;
  70. struct Window *WARP_Window;
  71. int WARP_NumTex= 40;        // Number of texcache entries
  72. ULONG WARP_ready = 0;
  73. extern ULONG gr_pixfmt;
  74.  
  75. //  Double-Buffering stuff
  76. int WARP_Buffer = 1;
  77. void *WARP_Buffers[2];
  78. ULONG WARP_BytesPerRow;
  79. ULONG WARP_PixelsPerRow;
  80.  
  81. //  Predefined textures
  82. W3D_Texture *WARP_Dummy = NULL;
  83. W3D_Texture *WARP_Trans = NULL;
  84. W3D_Texture *WARP_White = NULL;
  85. W3D_Texture *WARP_Reticle = NULL;
  86. W3D_Texture *WARP_Fireball = NULL;
  87. UWORD DummyTex[64*64];
  88. ULONG Fireball[64*64];
  89. UWORD TransTex[4] = {
  90.     0x8111, 0xa111,
  91.     0x5111, 0x7111
  92. };
  93. UWORD WhiteTex[4] = {
  94.     0xffff, 0xffff,
  95.     0xffff, 0xffff
  96. };
  97.  
  98. //  Reticle stuff
  99. UWORD ReticleTex[64*64];
  100. grs_bitmap *wreticle = NULL;
  101. UWORD rcol[] = {
  102.     0x0000,                     // 0: background
  103.     0xffff,                     // 1: crosshairs
  104.     0x8bbb,                     // 2: shield gauge
  105.     0x8bbb,                     // 3: energy gauge
  106.     0xaaaa,                     // 4: targeter
  107.     0xaaaa,                     // 5: normal laser left
  108.     0xaaaa,                     // 6: normal laser right
  109.     0x7666,                     // 7: left missile
  110.     0x7666,                     // 8: center missile
  111.     0x7666,                      // 9: right missile
  112.     0xaaaa,                     //10: dual laser left
  113.     0xaaaa,                     //11: dual laser right
  114.  
  115. };
  116.  
  117. W3D_Vertex rverts[4] = {
  118.     { 128,  78, 0,  0,  0, 1.0, 0.0, 1.0, 0.0, 1.0 },
  119.     { 192,  78, 0, 64,  0, 1.0, 0.0, 1.0, 0.0, 1.0 },
  120.     { 192, 142, 0, 64, 64, 1.0, 0.0, 1.0, 0.0, 1.0 },
  121.     { 128, 142, 0,  0, 64, 1.0, 0.0, 1.0, 0.0, 1.0 }
  122. };
  123.  
  124. W3D_Triangles rtris = {
  125.     4,
  126.     &rverts[0],
  127.     NULL,
  128.     NULL
  129. };
  130.  
  131.  
  132. //  Configuration parameters
  133. int WARP_TMap = 1;                      // TMapping on
  134. int WARP_MipMap = 0;                    // MipMapping off
  135. int WARP_Persp = 1;                     // Perspective correction on
  136. int WARP_TMapSub = 0;                   // Subdivider off
  137. int WARP_FogSub = 0;                    // Same for fogging
  138. int WARP_Fog = 0;                       // Fogging off
  139. int WARP_wreticle = 0;                  // Warp3D reticle
  140. int WARP_Modulate = 1;                  // Color effects
  141. int WARP_Filter = 1;                    // Texture filter
  142. int WARP_Depth = 0;                     // Depth filter
  143. int WARP_Dither = 1;                    // Dithering
  144. W3D_Float WARP_MFactor = 3.0;           // Color effect factor
  145. W3D_Fog WARP_FogParam = {
  146.     0.5,                                // Start at 0.5
  147.     0.2,                                // End at 0.2
  148.     1.0,                                // Density 1.0 (currently ignored)
  149.     0.0, 0.0, 0.0                       // Fog color (Black)
  150. };
  151.  
  152. //  Hinting parameters
  153. int WARP_HTMap  = 1;
  154. int WARP_HMMap  = 1;
  155. int WARP_HBif   = 1;
  156. int WARP_HDf    = 1;
  157. int WARP_HPers  = 1;
  158. int WARP_HBlend = 1;
  159. int WARP_HFog   = 1;
  160. int WARP_HAnti  = 1;
  161. int WARP_HDith  = 1;
  162. ULONG Hints[3] = {W3D_H_FAST, W3D_H_AVERAGE, W3D_H_NICE};
  163.  
  164. //  Direct-access stuff
  165. UWORD BitValues[256];
  166. UWORD BitValuesTexture[256];
  167. extern ULONG palette[800];
  168. int WARP_BitValues = 0;
  169. int WARP_automap_active = 0;
  170.  
  171. //  Prototypes
  172. void WARP_Close(void);
  173. void WARP_UpdateImage(W3D_Texture *tex, void *data);
  174. void WARP_UpdateTextureCache(void);
  175. void WARP_UpdateState(void);
  176. void WARP_UpdateFog(void);
  177. void WARP_UpdateHints(void);
  178. void WARP_init_reticle(void);
  179. void WARP_GenFireball(void);
  180.  
  181. //  Externals
  182. extern UBYTE *OffscreenBuffer;
  183. extern int OffscreenW;
  184. extern int OffscreenH;
  185. extern int OffscreenSize;
  186. extern struct Window *win;
  187. extern struct Screen *scr;
  188. extern struct ScreenBuffer *sb1, *sb2;
  189. extern unsigned long Mode320x200;
  190. extern unsigned long Mode320x400;
  191. extern unsigned long Mode640x480;
  192. extern unsigned long Mode800x600;
  193. extern int farg;
  194. extern int wbmode;
  195. extern UWORD *PointerData;
  196.  
  197. extern char *gr_sc_small;
  198. extern char *gr_sc_medium;
  199. extern char *gr_sc_large;
  200. extern char ScreenType;
  201. extern int depth;
  202. extern PLANEPTR planes;
  203. extern double wscale;
  204. extern double hscale;
  205. extern UBYTE *compare_buffer;
  206. extern int VR_screen_mode;
  207. extern int VR_render_width;
  208. extern int VR_render_height;
  209.  
  210.  
  211. #ifdef PROF_CACHE
  212. //  Used for cache statistics
  213. ULONG WARP_S_Update = 0;            // UpdateTexImage calls
  214. ULONG WARP_S_Find = 0;              // FindTexture
  215. ULONG WARP_S_Miss = 0;              // Cache misses
  216. ULONG WARP_S_Invalid = 0;           // Invalidations
  217. ULONG WARP_S_Make = 0;              // Texture conversion
  218. ULONG WARP_S_Clear = 0;             // Clearings
  219. #endif
  220.  
  221.  
  222. /*
  223. ** Texture cache structure
  224. */
  225. typedef struct {
  226.     W3D_Texture *TexObj;        // Pointer to the associated TexObj
  227.     APTR SourceData;            // Source Data of texture
  228.     ULONG LastAccess;           // Last time this was accessed
  229.     grs_bitmap *ref;            // Reference in Descent Texture Cache
  230. } WarpTextureCache;
  231.  
  232. WarpTextureCache *WTCache;      // Allocated Texture Array
  233.  
  234. /*
  235. ** Initializes the texture cache
  236. ** Allocates texture objects
  237. ** Allocates Cache array
  238. */
  239. void WARP_InitTextureCache(void)
  240. {
  241.     int i;
  242.     ULONG error;
  243.     struct TagItem tags [] = {
  244.         {W3D_ATO_IMAGE,     (ULONG)DummyTex},
  245.         {W3D_ATO_FORMAT,    W3D_A1R5G5B5},
  246.         {W3D_ATO_WIDTH,     64},
  247.         {W3D_ATO_HEIGHT,    64},
  248.         {TAG_DONE,          0}
  249.     };
  250.  
  251.     struct TagItem Mtags [] = {
  252.         {W3D_ATO_IMAGE,     (ULONG)DummyTex},
  253.         {W3D_ATO_FORMAT,    W3D_A1R5G5B5},
  254.         {W3D_ATO_WIDTH,     64},
  255.         {W3D_ATO_HEIGHT,    64},
  256.         {W3D_ATO_MIPMAP,    0x3f},
  257.         {TAG_DONE,          0}
  258.     };
  259.  
  260.  
  261.     debug(("WARP_InitTextureCache: Creating texture cache using %d entries\n", WARP_NumTex));
  262.  
  263.     WTCache = malloc(sizeof(WarpTextureCache)*WARP_NumTex);
  264.     if (!WTCache) {
  265.         printf("Unable to create texture cache\n");
  266.         exit(0);
  267.     }
  268.  
  269.     for (i=0; i<WARP_NumTex; i++) {
  270.         if (WARP_MipMap)
  271.             WTCache[i].TexObj = W3D_AllocTexObj(WARP_Context, &error, Mtags);
  272.         else
  273.             WTCache[i].TexObj = W3D_AllocTexObj(WARP_Context, &error, tags);
  274.         if (error != W3D_SUCCESS) {
  275.             printf("Texture cache initialization failed because of error %d\n", error);
  276.             exit(0);
  277.         }
  278.         WTCache[i].SourceData = NULL;
  279.         WTCache[i].LastAccess = 0;
  280.         WTCache[i].ref        = NULL;
  281.         W3D_SetTexEnv(WARP_Context, WTCache[i].TexObj, W3D_MODULATE, NULL);
  282.         W3D_SetBlendMode(WARP_Context, W3D_SRC_ALPHA, W3D_ONE_MINUS_SRC_ALPHA);
  283.         W3D_SetWrapMode(WARP_Context, WTCache[i].TexObj, W3D_REPEAT, W3D_REPEAT, NULL);
  284.     }
  285.     WARP_UpdateTextureCache();
  286.     debug(("WARP_InitTextureCache: Done\n"));
  287. }
  288.  
  289. /*
  290. ** Frees all memory associated with texture cache and texture objects
  291. */
  292. void WARP_DeleteTextureCache(void)
  293. {
  294.     int i;
  295.     if (!WTCache) return;
  296.  
  297.     debug(("WARP_DeleteTextureCache: Freeing texture cache\n"));
  298.  
  299.     if (WARP_ready != 0) {
  300.         for (i=0; i<WARP_NumTex; i++) {
  301.             W3D_FreeTexObj(WARP_Context, WTCache[i].TexObj);
  302.         }
  303.     } else {
  304.         printf("Warning: Freeing texture cache while Warp3D is disabled\n");
  305.     }
  306.  
  307.     free(WTCache);
  308.     WTCache = NULL;
  309.     debug(("WARP_DeleteTextureCache: Done\n"));
  310. }
  311.  
  312. /*
  313. ** Invalidate all entries in the texture cache
  314. */
  315. void WARP_ClearTextureCache(void)
  316. {
  317.     int i;
  318.     if (WARP_ready == 0) return;
  319. #ifdef PROF_CACHE
  320.     WARP_S_Clear++;
  321. #endif
  322.     if (!WTCache || WARP_ready == 0) return;
  323.     debug(("WARP_ClearTextureCache: Clearing Texture Cache\n"));
  324.     for (i=0; i<WARP_NumTex; i++) {
  325.         WTCache[i].ref = NULL;
  326.     }
  327.     debug(("WARP_ClearTextureCache: Done\n"));
  328. }
  329.  
  330.  
  331. /*
  332. **  WARP_SingleBuffer
  333. **  Make sure the first buffer is set
  334. */
  335. #ifndef SCBUF
  336. void WARP_SingleBuffer(void)
  337. {
  338.     static int active = 0;
  339.     W3D_Scissor s = {0,0, win->Width, win->Height/2};
  340.     struct Screen *scr = win->WScreen;
  341.     struct ViewPort *vp = &(scr->ViewPort);
  342.  
  343.     if (active == 0) {
  344.         W3D_SetDrawRegion(WARP_Context, win->RPort->BitMap, 0, &s);
  345.         vp->RasInfo->RyOffset = 0;
  346.         ScrollVPort(vp);
  347.         active = 1;
  348.     }
  349. }
  350. #else
  351. void WARP_SwitchBuffer(void);
  352.  
  353. void WARP_SingleBuffer(void)
  354. {
  355.     W3D_Scissor s = {0,0, win->Width, win->Height/2};
  356.     struct Screen *scr = win->WScreen;
  357.     struct ViewPort *vp = &(scr->ViewPort);
  358.  
  359.     if (WARP_Buffer != 0) {
  360.         WARP_SwitchBuffer();
  361.     }
  362.  
  363. }
  364. #endif
  365.  
  366.  
  367. /*
  368. **  WARP_SwitchBuffer
  369. **  Switch buffer for double buffering
  370. */
  371. #ifndef SCBUF
  372. void WARP_SwitchBuffer(void)
  373. {
  374.     W3D_Scissor s = {0,0, win->Width, win->Height/2};
  375.     struct Screen *scr = win->WScreen;
  376.     struct ViewPort *vp = &(scr->ViewPort);
  377.  
  378.     W3D_WaitIdle(WARP_Context);
  379.  
  380.     if (WARP_Buffer == 0) {
  381.         vp->RasInfo->RyOffset = win->Height/2;
  382.         ScrollVPort(vp);
  383.         W3D_SetDrawRegion(WARP_Context, win->RPort->BitMap, 0, &s);
  384.         WARP_Buffer = 1;
  385.     } else {
  386.         vp->RasInfo->RyOffset = 0;
  387.         ScrollVPort(vp);
  388.         W3D_SetDrawRegion(WARP_Context, win->RPort->BitMap,
  389.             win->Height/2, &s);
  390.         WARP_Buffer = 0;
  391.     }
  392. }
  393. #else
  394. void WARP_SwitchBuffer(void)
  395. {
  396.     W3D_Scissor s = {0,0, win->Width, win->Height/2};
  397.     struct Screen *scr = win->WScreen;
  398.     struct ViewPort *vp = &(scr->ViewPort);
  399.  
  400.     W3D_WaitIdle(WARP_Context);
  401.  
  402.     if (WARP_Buffer == 0) {
  403.         ChangeScreenBuffer(scr, sb2);
  404.         WaitBOVP(&(scr->ViewPort));
  405.         WARP_Buffer = 1;
  406.     } else {
  407.         ChangeScreenBuffer(scr, sb1);
  408.         WaitBOVP(&(scr->ViewPort));
  409.         WARP_Buffer = 0;
  410.     }
  411. }
  412. #endif
  413.  
  414.  
  415. /*
  416. **  WARP_Update
  417. **  WritePixelArray wrapper
  418. */
  419. void WARP_Update(int y)
  420. {
  421.     if (gr_keep_resolution == 0) {
  422.         WritePixelArray(OffscreenBuffer, 0, 0, OffscreenW, win->RPort, 0, y,
  423.             OffscreenW, OffscreenH, RECTFMT_LUT8);
  424.     } else {
  425.         /*ScalePixelArray(OffscreenBuffer, 320, 200, 320, win->RPort, 0, y,
  426.             win->Width, win->Height*0.5, RECTFMT_LUT8);*/ // Until Cybergraphics solves this...
  427.         if (!WARP_automap_active) {
  428.             WritePixelArray(OffscreenBuffer, 0, 0, 320, win->RPort, win->Width*0.5-160, y+(win->Height*0.25)-100,
  429.                 320, 200, RECTFMT_LUT8);
  430.         } else {
  431.             WritePixelArray(OffscreenBuffer, 0, 0, VR_render_width, win->RPort, 0, y,
  432.                 VR_render_width, VR_render_height, RECTFMT_LUT8);
  433.         }
  434.     }
  435.  
  436.     WARP_SwitchBuffer();
  437. }
  438.  
  439.  
  440. /*
  441. **  WARP_Error
  442. **  Print error message
  443. */
  444. void WARP_Error(ULONG code)
  445. {
  446.     switch (code) {
  447.         case W3D_SUCCESS:           printf("No error\n"); break;
  448.         case W3D_ILLEGALINPUT:      printf("Illegal input\n"); break;
  449.         case W3D_NOMEMORY:          printf("No memory left\n"); break;
  450.         case W3D_NODRIVER:          printf("No driver is loaded\n"); break;
  451.         case W3D_UNSUPPORTEDFMT:    printf("The bitmap format is not supported\n"); break;
  452.         case W3D_ILLEGALBITMAP:     printf("The bitmap is not initialized correctly\n"); break;
  453.         case W3D_UNSUPPORTEDTEXSIZE:printf("Unsupported texture size\n");
  454.         case W3D_NOPALETTE:         printf("Need palette\n");
  455.         default:                    printf("Unknown error code\n"); break;
  456.     }
  457. }
  458.  
  459.  
  460. /*
  461. **  WARP_Init
  462. **  Initialise the Warp3D subsystem
  463. */
  464. void WARP_Init(struct Window *win, ULONG mode)
  465. {
  466.     /*
  467.     ** Some of the tag's ti_Data fields are filled in later
  468.     */
  469.     struct TagItem tags[] = {
  470.         {W3D_CC_BITMAP,     NULL},
  471.         {W3D_CC_YOFFSET,    0},
  472.         {W3D_CC_DRIVERTYPE, W3D_DRIVER_BEST},
  473.         {W3D_CC_DOUBLEHEIGHT,TRUE},
  474.         {W3D_CC_FAST,       TRUE},
  475.         {W3D_CC_INDIRECT,   FALSE},             //  set later
  476.         {W3D_CC_MODEID,     0},
  477.         {TAG_DONE,          0}
  478.     };
  479.  
  480.     struct TagItem ATO_Tags[] = {
  481.         {W3D_ATO_IMAGE,     (ULONG)DummyTex},
  482.         {W3D_ATO_FORMAT,    W3D_A1R5G5B5},
  483.         {W3D_ATO_WIDTH,     64},
  484.         {W3D_ATO_HEIGHT,    64}
  485.     };
  486.  
  487.     struct TagItem ATO_TagsT[] = {
  488.         {W3D_ATO_IMAGE,     (ULONG)TransTex},
  489.         {W3D_ATO_FORMAT,    W3D_A4R4G4B4},
  490.         {W3D_ATO_WIDTH,     2},
  491.         {W3D_ATO_HEIGHT,    2}
  492.     };
  493.  
  494.     struct TagItem ATO_TagsW[] = {
  495.         {W3D_ATO_IMAGE,     (ULONG)WhiteTex},
  496.         {W3D_ATO_FORMAT,    W3D_A1R5G5B5},
  497.         {W3D_ATO_WIDTH,     2},
  498.         {W3D_ATO_HEIGHT,    2}
  499.     };
  500.  
  501.  
  502.     /*
  503.     ** Height is used to calculate the real display height
  504.     ** and the correct offset for double buffering
  505.     **
  506.     ** CError is used as an error variable during context creation
  507.     */
  508.     ULONG Height, CError;
  509.  
  510.     /*
  511.     ** Used for LockBitmap
  512.     */
  513.     void *handle;
  514.     UBYTE *scrn;
  515.     ULONG bpr;
  516.     int i;
  517.  
  518.     debug(("WARP_Init: Initialising Warp3D\n"));
  519.  
  520. #if 0
  521.     //  Free existing context (if any)
  522.     if (WARP_Context) {
  523.         WARP_DeleteTextureCache();
  524.         if (WARP_Dummy) W3D_FreeTexObj(WARP_Context, WARP_Dummy);
  525.         if (WARP_Trans) W3D_FreeTexObj(WARP_Context, WARP_Trans);
  526.         if (WARP_White) W3D_FreeTexObj(WARP_Context, WARP_White);
  527.         if (WARP_Reticle) W3D_FreeTexObj(WARP_Context, WARP_Reticle);
  528.         W3D_DestroyContext(WARP_Context);
  529.         WARP_Context = NULL;
  530.         WARP_Dummy = NULL;
  531.         WARP_Trans = NULL;
  532.         WARP_White = NULL;
  533.         WARP_Reticle = NULL;
  534.     }
  535. #endif
  536.         // Insert values into Taglist
  537.         Height = win->Height / 2;
  538.         tags[0].ti_Data = (ULONG)(win->RPort->BitMap);
  539.         tags[1].ti_Data = Height;
  540.         if (FindArg("-indirect"))
  541.             tags[5].ti_Data = TRUE;
  542.         else
  543.             tags[5].ti_Data = FALSE;
  544.  
  545.     tags[6].ti_Data = mode;
  546.  
  547.     if (!WARP_Context) {
  548.         // Create context
  549.         WARP_Context = W3D_CreateContext(&CError, tags);
  550.         if (!WARP_Context) {
  551.             printf("ERROR: W3D_CreateContext failed:");
  552.             WARP_Error(CError);
  553.             exit(0);
  554.         }
  555.  
  556.         debug(("WARP_Init: Setting state\n"));
  557.         W3D_SetState(WARP_Context, W3D_GOURAUD, W3D_ENABLE);
  558.         W3D_SetState(WARP_Context, W3D_TEXMAPPING, W3D_ENABLE);
  559.         W3D_SetState(WARP_Context, W3D_BLENDING, W3D_ENABLE);
  560.         W3D_SetState(WARP_Context, W3D_PERSPECTIVE, W3D_ENABLE);
  561.         W3D_SetBlendMode(WARP_Context, W3D_SRC_ALPHA, W3D_ONE_MINUS_SRC_ALPHA);
  562.     } else {
  563.         debug(("WARP_Init: Setting draw region\n"));
  564.         W3D_SetDrawRegion(WARP_Context, (win->RPort->BitMap), 0, NULL);
  565.         debug(("WARP_Init: New bitmap is %ld×%ld\n", WARP_Context->width,
  566.                 WARP_Context->height));
  567.     }
  568.  
  569.     //  Initialize Double buffering
  570.     Forbid();
  571.     handle = LockBitMapTags(win->RPort->BitMap,
  572.         LBMI_BASEADDRESS,   (ULONG)&scrn,
  573.         LBMI_BYTESPERROW,   (ULONG)&bpr,
  574.     TAG_DONE);
  575.     UnLockBitMap(handle);
  576.     Permit();
  577.     WARP_Buffers[0] = (void *)scrn;
  578.     WARP_Buffers[1] = (void *)((char *)scrn+bpr*Height);
  579.     WARP_BytesPerRow = bpr;
  580.     WARP_PixelsPerRow = bpr/2;
  581.     WARP_Buffer = 1;        // Draw to second buffer
  582.     WARP_Window = win;
  583.  
  584.     if (WARP_Dummy) {
  585.         //  Create Dummy texture
  586.         debug(("WARP_Init: Creating dummy texture\n"));
  587.         for (i = 0; i < 64*64; i++) {
  588.             if (i%2) DummyTex[i] = 0xffff;
  589.             else     DummyTex[i] = 0x0;
  590.         }
  591.         WARP_Dummy = W3D_AllocTexObj(WARP_Context, &CError, ATO_Tags);
  592.         if (CError != W3D_SUCCESS) {
  593.             printf("Warning: W3D_AllocTexObj failed for dummy texture:");
  594.             WARP_Error(CError);
  595.         } else {
  596.             debug(("WARP_Init: Dummy at 0x%x\n", WARP_Dummy));
  597.         }
  598.         W3D_SetWrapMode(WARP_Context, WARP_Dummy, W3D_REPEAT, W3D_REPEAT, NULL);
  599.         W3D_SetTexEnv(WARP_Context, WARP_Dummy, W3D_MODULATE, NULL);
  600.         W3D_SetFilter(WARP_Context, WARP_Dummy, W3D_LINEAR, W3D_LINEAR);
  601.     }
  602.  
  603.     if (WARP_Trans) {
  604.         //  Create Transparent texture
  605.         debug(("WARP_Init: Creating transparent texture\n"));
  606.         WARP_Trans = W3D_AllocTexObj(WARP_Context, &CError, ATO_TagsT);
  607.         if (CError != W3D_SUCCESS) {
  608.             printf("Warning: W3D_AllocTexObj failed for transparency texture:");
  609.             WARP_Error(CError);
  610.         }
  611.         W3D_SetWrapMode(WARP_Context, WARP_Trans, W3D_REPEAT, W3D_REPEAT, NULL);
  612.         W3D_SetTexEnv(WARP_Context, WARP_Trans, W3D_MODULATE, NULL);
  613.         W3D_SetFilter(WARP_Context, WARP_Trans, W3D_LINEAR, W3D_LINEAR);
  614.  
  615.         debug(("WARP_Init: Creating white texture\n"));
  616.         WARP_White = W3D_AllocTexObj(WARP_Context, &CError, ATO_TagsW);
  617.         if (CError != W3D_SUCCESS) {
  618.             printf("Warning: W3D_AllocTexObj failed for white texture:");
  619.             WARP_Error(CError);
  620.         }
  621.         W3D_SetWrapMode(WARP_Context, WARP_White, W3D_REPEAT, W3D_REPEAT, NULL);
  622.         W3D_SetTexEnv(WARP_Context, WARP_White, W3D_MODULATE, NULL);
  623.         W3D_SetFilter(WARP_Context, WARP_White, W3D_NEAREST, W3D_NEAREST);
  624.     }
  625.  
  626.     //  Init reticle
  627.     WARP_init_reticle();
  628.  
  629.     //  Create fireball
  630.     WARP_GenFireball();
  631.  
  632.     //  Create texture cache
  633.     debug(("WARP_Init: Initializing texture cache\n"));
  634.     if (!WTCache) WARP_InitTextureCache();
  635.  
  636.     WARP_ready = 1;
  637.  
  638.     //  Settings
  639.     WARP_UpdateHints();
  640. #if 0
  641.     WARP_UpdateFog();
  642.     WARP_UpdateTextureCache();
  643.     WARP_UpdateState();
  644. #endif
  645.  
  646.     //  Schedule closing of Warp on exit
  647.     atexit(WARP_Close);
  648.     debug(("WARP_Init: Done\n"));
  649. }
  650.  
  651. /*
  652. **  WARP_FirstBuffer
  653. **  Make sure the first buffer is active
  654. */
  655. void* WARP_FirstBuffer(void)
  656. {
  657.         if (WARP_Buffer == 0) return WARP_GetBufferAddress();
  658.         WARP_SwitchBuffer();
  659.         return WARP_GetBufferAddress();
  660. }
  661.  
  662.  
  663. /*
  664. **  WARP_Close
  665. **  Free everything WarpP3D-Related
  666. */
  667. void WARP_Close(void)
  668. {
  669.     if (WARP_ready == 0) return;
  670.  
  671.     debug(("WARP_Close: Closing Warp3D\n"));
  672.  
  673.     debug(("WARP_Close: Deleting texture cache\n"));
  674.     WARP_DeleteTextureCache();
  675.  
  676.     if (WARP_Dummy) {
  677.         debug(("WARP_Close: Deleting dummy\n"));
  678.         W3D_FreeTexObj(WARP_Context, WARP_Dummy);
  679.     }
  680.  
  681.     if (WARP_Trans) {
  682.         debug(("WARP_Close: Deleting transparency texture\n"));
  683.         W3D_FreeTexObj(WARP_Context, WARP_Trans);
  684.     }
  685.  
  686.     if (WARP_White) {
  687.         debug(("WARP_Close: Deleting white texture\n"));
  688.         W3D_FreeTexObj(WARP_Context, WARP_White);
  689.     }
  690.  
  691.     if (WARP_Reticle) {
  692.         debug(("WARP_Close: Deleting reticle texture\n"));
  693.         W3D_FreeTexObj(WARP_Context, WARP_Reticle);
  694.         if (wreticle) gr_free_bitmap(wreticle);
  695.     }
  696.  
  697.     if (WARP_Fireball) {
  698.         debug(("WARP_Close: Deleting fireball texture\n"));
  699.         W3D_FreeTexObj(WARP_Context, WARP_Fireball);
  700.     }
  701.  
  702.     if (WARP_Context) {
  703.         debug(("WARP_Close: Deleting context\n"));
  704.         W3D_DestroyContext(WARP_Context);
  705.         WARP_Context = NULL;
  706.     }
  707.  
  708.     WARP_ready = 0;
  709.  
  710.     debug(("WARP_Close: Done\n"));
  711.  
  712. #ifdef PROF_CACHE
  713.     printf("\nStatistics for texture cache:\n");
  714.     printf(  "-----------------------------\n");
  715.     printf("Calls to UpdateTexImage:    %8d\n", WARP_S_Update);
  716.     printf("Single invalidations:       %8d\n", WARP_S_Invalid);
  717.     printf("Texture creation:           %8d\n", WARP_S_Make);
  718.     printf("Total cache invalidations:  %8d\n", WARP_S_Clear);
  719.     printf("Cache accesses:             %8d\n", WARP_S_Find);
  720.     printf("Cache misses:               %8d\n", WARP_S_Miss);
  721.     printf("Hit/Miss ratio:             %8.3g%\n", 100 - (((float)WARP_S_Miss/(float)WARP_S_Find) * 100.0));
  722.     printf("\n");
  723. #endif
  724. }
  725.  
  726.  
  727. /*
  728. **  WARP_Kludge
  729. **  RectFil to get around the Text() bug
  730. */
  731. void WARP_Kludge(void)
  732. {
  733. //    RectFill(win->RPort, 0, 0, 0, 0);
  734. }
  735.  
  736. // Now a macro
  737. #if 0
  738. /*
  739. **  WARP_GetBufferAddress
  740. **  Get address of current buffer
  741. */
  742. void *WARP_GetBufferAddress(void)
  743. {
  744.   return WARP_Buffers[1-WARP_Buffer];
  745. }
  746. #endif
  747.  
  748. /*
  749. ** Generates an array of 16 bit words for the generation of textures.
  750. ** Words are in the format ARGB1555
  751. */
  752. void WARP_MakeBitValues(void)
  753. {
  754.     ubyte r,g,b;
  755.     int i;
  756.     // Leave if the values are computed
  757.     if (WARP_BitValues == 1) return;
  758.  
  759.     // Make sure the palette is completely faded in
  760.     if (gr_palette_faded_out) gr_palette_fade_in(gr_palette, 1,0);
  761.  
  762.     // Build the ARGB table. Alpha value is always 1, meaning
  763.     // full opacity.
  764.     // The strange shift values are because Descent uses a 64 step
  765.     // VGA palette
  766.     for (i=0; i<255; i++) {
  767.         r=palette[1+i*3]>>24;
  768.         g=palette[1+i*3+1]>>24;
  769.         b=palette[1+i*3+2]>>24;
  770.         switch (gr_pixfmt) {
  771.         case PIXFMT_RGB15:
  772.             BitValues[i] = 0x8000 | (r&0xF8)<<7 | (g&0xF8)<<2 | (b&0xF8)>>3;
  773.             break;
  774.         case PIXFMT_RGB15PC:
  775.             BitValues[i] = 0x8000 | (r&0xF8)<<7 | (g&0xF8)<<2 | (b&0xF8)>>3;
  776.             BitValues[i] = (BitValues[i]>>8) & 0x00ff | (BitValues[i]<<8) & 0xff00;
  777.             break;
  778.         case PIXFMT_BGR15:
  779.             BitValues[i] = 0x8000 | (b&0xF8)<<7 | (g&0xF8)<<2 | (r&0xF8)>>3;
  780.             break;
  781.         case PIXFMT_BGR15PC:
  782.             BitValues[i] = 0x8000 | (b&0xF8)<<7 | (g&0xF8)<<2 | (r&0xF8)>>3;
  783.             BitValues[i] = (BitValues[i]>>8) & 0x00ff | (BitValues[i]<<8) & 0xff00;
  784.             break;
  785.         }
  786.         BitValuesTexture[i] = 0x8000 | (r&0xF8)<<7 | (g&0xF8)<<2 | (b&0xF8)>>3;
  787.     }
  788.     // BitValue 255 is set to zero to indicate full transparency
  789.     BitValues[255] = 0;
  790.     BitValuesTexture[255] = 0;
  791.     // Make those values valid
  792.     WARP_BitValues=1;
  793.     // Invalidate the texture cache, so that new textures
  794.     // are correctly re-calculated.
  795.     WARP_ClearTextureCache();
  796. }
  797.  
  798. /*
  799. ** Makes the BitValue array, but invalidates it immediately
  800. ** Used for temporarily allocating textures.
  801. */
  802. void WARP_MakeTempBitValues(void)
  803. {
  804.     WARP_MakeBitValues();
  805.     WARP_BitValues=0;
  806. }
  807.  
  808. /*
  809. ** Convert a LUT8 texture to ARGB.
  810. **
  811. ** The process is straigtforward, since the required information
  812. ** is available in the BitArray
  813. **
  814. ** Uses the BitArray supplied to convert from source BYTES to
  815. ** target WORDS
  816. */
  817. void WARP_MakeARGBTexture(UWORD *BitArray, UBYTE *source, UWORD *target)
  818. {
  819.     /*
  820.     ** Implementation note:
  821.     ** I didn't use a for loop because the loop below is easier to optimizes. The
  822.     ** compiler will detect that the variable <i> is not needed, and optimize it
  823.     ** away...
  824.     **
  825.     ** For maximum speed, this loop could be unrolled a few times. However,
  826.     ** experience showed that this routine is actually seldomly called.
  827.     */
  828.     int i;
  829. #ifdef PROF_CACHE
  830.     WARP_S_Make++;
  831. #endif
  832.     i=4096;
  833.     while (i) {
  834.         *target++=*(BitArray+*source++);
  835.         i--;
  836.     }
  837. }
  838.  
  839. /*
  840. ** Get Oldest Entry in the texture cache
  841. **
  842. ** This routine looks through the texture cache and searches for the
  843. ** least recently used entry. I could have done this using a self-organizing
  844. ** list, but this would have introduced additional overhead during the
  845. ** case when the texture was actually cached. Since the cache-miss case
  846. ** is much more infrequent (around 98% are hits), I chose this implementation.
  847. */
  848. int WARP_GetOldestEntry(void)
  849. {
  850.     int i;
  851.     int oldidx=0;
  852.     for (i=0; i<WARP_NumTex; i++) {
  853.         if (WTCache[i].LastAccess < WTCache[oldidx].LastAccess) {
  854.             oldidx = i;
  855.         }
  856.     }
  857.     return oldidx;
  858. }
  859.  
  860. /*
  861. ** Invalidate the cache entry associated with the given bitmap
  862. */
  863. void WARP_InvalidCacheEntry(grs_bitmap *map)
  864. {
  865.     int i = (int)map->bm_Handle;
  866. #ifdef PROF_CACHE
  867.     WARP_S_Invalid++;
  868. #endif
  869.     map->bm_Handle = 0;
  870.     if (i>=WARP_NumTex || i<=0) return;
  871.     if (WTCache[i].ref != map) return;
  872.     WTCache[i].ref = NULL;
  873.     WTCache[i].LastAccess = 0;
  874. }
  875.  
  876. /*
  877. ** Find a texture
  878. **
  879. ** Tries to find the texture corresponding to a given bitmap
  880. ** If the texture is not cached, the least recently used texture
  881. ** is killed, and a new entry is created for that.
  882. */
  883. W3D_Texture* WARP_FindTexture(grs_bitmap *map)
  884. {
  885.     int i;
  886.     grs_bitmap *oldmap = map;
  887.     fix now = timer_get_fixed_seconds();
  888.  
  889. #ifdef PROF_CACHE
  890.     WARP_S_Find++;
  891. #endif
  892.  
  893.     WARP_MakeBitValues();   // Create bit values if not present
  894.  
  895.     // If this bitmap has a handle, check if it is valid
  896.     if (map->bm_Handle) {
  897.         if (WTCache[(int)map->bm_Handle].ref == map) {
  898.             WTCache[(int)map->bm_Handle].LastAccess = now;
  899.             return WTCache[(int)map->bm_Handle].TexObj;
  900.         } else {
  901.             map->bm_Handle = 0;
  902.         }
  903.     }
  904.  
  905.     /*
  906.     ** Cache miss
  907.     ** The bitmap was not in the cache, or the cache entry has
  908.     ** already been invalidated.
  909.     **
  910.     */
  911.  
  912. #ifdef PROF_CACHE
  913.     WARP_S_Miss++;
  914. #endif
  915.  
  916.     // Step one     expand a compressed texture
  917.     if (map->bm_flags & BM_FLAG_RLE)
  918.         map = rle_expand_texture(map);
  919.  
  920.  
  921.     // Step two     find a suitable entry
  922.     i = WARP_GetOldestEntry();
  923.  
  924.     // Step three   make a texture and upload it
  925.     if (map == NULL || map->bm_data == NULL) {
  926.         int j;
  927.         for (j=0; j<4096; j++) DummyTex[i] = 0xffff;
  928.     } else {
  929.         WARP_MakeARGBTexture(BitValuesTexture, map->bm_data, DummyTex);
  930.     }
  931.  
  932.     WARP_UpdateImage(WTCache[i].TexObj, DummyTex);
  933.  
  934.     // Use the handle field to store the cache entry for fast retrieval
  935.     oldmap->bm_Handle = (void *)i;
  936.  
  937.     // Set the reference pointer and time code
  938.     WTCache[i].ref          = oldmap;
  939.     WTCache[i].LastAccess   = now;
  940.  
  941.     return WTCache[i].TexObj;
  942. }
  943.  
  944.  
  945. /*
  946. **  WARP_UpdateImage
  947. **  Warpper for UpdateTexImage
  948. */
  949. void WARP_UpdateImage(W3D_Texture *tex, void *data)
  950. {
  951.     ULONG error;
  952.     int i;
  953.  
  954.     error = W3D_UpdateTexImage(WARP_Context, tex, data, 0, NULL);
  955.  
  956.     if (error != W3D_SUCCESS)
  957.         printf("Warning: W3D_UpdateTexImage returned %d\n", error);
  958.  
  959.  
  960. #ifdef PROF_CACHE
  961.     WARP_S_Update++;
  962. #endif
  963. }
  964.  
  965.  
  966. /*
  967. **  WARP_UpdateState
  968. **  Updates the state according to user preferences
  969. */
  970. void WARP_UpdateState(void)
  971. {
  972.     if (WARP_Persp == 0)        W3D_SetState(WARP_Context, W3D_PERSPECTIVE, W3D_DISABLE);
  973.     else                        W3D_SetState(WARP_Context, W3D_PERSPECTIVE, W3D_ENABLE);
  974.  
  975.     if (WARP_TMap == 0)         W3D_SetState(WARP_Context, W3D_TEXMAPPING, W3D_DISABLE);
  976.     else                        W3D_SetState(WARP_Context, W3D_TEXMAPPING, W3D_ENABLE);
  977.  
  978.     if (WARP_Dither == 0)       W3D_SetState(WARP_Context, W3D_DITHERING, W3D_DISABLE);
  979.     else                        W3D_SetState(WARP_Context, W3D_DITHERING, W3D_ENABLE);
  980.  
  981.     WARP_Persp =  (W3D_GetState(WARP_Context, W3D_PERSPECTIVE) == W3D_ENABLED ? 1: 0);
  982.     WARP_TMap =   (W3D_GetState(WARP_Context, W3D_TEXMAPPING) == W3D_ENABLED ? 1: 0);
  983.     WARP_Dither = (W3D_GetState(WARP_Context, W3D_DITHERING) == W3D_ENABLED ? 1: 0);
  984.  
  985.     WARP_ClearTextureCache();
  986. }
  987.  
  988. /*
  989. **  WARP_UpdateTextureCache
  990. **  Update the textures' filter modes
  991. */
  992. void WARP_UpdateTextureCache(void)
  993. {
  994.     int i;
  995.     ULONG filter, mfilter;
  996.  
  997.     if (WARP_Filter == 0)    filter = W3D_NEAREST;
  998.     if (WARP_Filter == 1)    filter = W3D_LINEAR;
  999.     mfilter = filter;
  1000.  
  1001.     if (WARP_MipMap) {
  1002.         if (filter == W3D_NEAREST && WARP_Depth == 0) filter = W3D_NEAREST_MIP_NEAREST;
  1003.         if (filter == W3D_NEAREST && WARP_Depth == 1) filter = W3D_NEAREST_MIP_LINEAR;
  1004.         if (filter == W3D_LINEAR && WARP_Depth == 0)  filter = W3D_LINEAR_MIP_NEAREST;
  1005.         if (filter == W3D_LINEAR && WARP_Depth == 1)  filter = W3D_LINEAR_MIP_LINEAR;
  1006.     }
  1007.  
  1008.     for (i=0; i<WARP_NumTex; i++)
  1009.         W3D_SetFilter(WARP_Context, WTCache[i].TexObj, filter, mfilter);
  1010.  
  1011.     WARP_ClearTextureCache();
  1012. }
  1013.  
  1014.  
  1015. /*
  1016. **  WARP_UpdateFog
  1017. **  Update and set fogging
  1018. */
  1019. void WARP_UpdateFog(void)
  1020. {
  1021.     if (WARP_Fog == 0)      W3D_SetState(WARP_Context, W3D_FOGGING, W3D_DISABLE);
  1022.     else {
  1023.         W3D_SetState(WARP_Context, W3D_FOGGING, W3D_ENABLE);
  1024.         W3D_SetFogParams(WARP_Context, &WARP_FogParam, W3D_FOG_INTERPOLATED);
  1025.     }
  1026.     WARP_ClearTextureCache();
  1027. }
  1028.  
  1029. /*
  1030. **  WARP_UpdateHints
  1031. **  Update the W3D_Hint
  1032. */
  1033. void WARP_UpdateHints(void)
  1034. {
  1035.     W3D_Hint(WARP_Context, W3D_H_TEXMAPPING,        Hints[WARP_HTMap]);
  1036.     W3D_Hint(WARP_Context, W3D_H_MIPMAPPING,        Hints[WARP_HMMap]);
  1037.     W3D_Hint(WARP_Context, W3D_H_BILINEARFILTER,    Hints[WARP_HBif]);
  1038.     W3D_Hint(WARP_Context, W3D_H_MMFILTER,          Hints[WARP_HDf]);
  1039.     W3D_Hint(WARP_Context, W3D_H_PERSPECTIVE,       Hints[WARP_HPers]);
  1040.     W3D_Hint(WARP_Context, W3D_H_BLENDING,          Hints[WARP_HBlend]);
  1041.     W3D_Hint(WARP_Context, W3D_H_FOGGING,           Hints[WARP_HFog]);
  1042.     W3D_Hint(WARP_Context, W3D_H_ANTIALIASING,      Hints[WARP_HAnti]);
  1043.     W3D_Hint(WARP_Context, W3D_H_DITHERING,         Hints[WARP_HDith]);
  1044.     WARP_ClearTextureCache();
  1045. }
  1046.  
  1047. /*
  1048. **  WARP_init_reticle
  1049. **  Initialise the warp reticle
  1050. */
  1051. void WARP_init_reticle(void)
  1052. {
  1053.     struct TagItem ATO_Tags[] = {
  1054.         {W3D_ATO_IMAGE,     (ULONG)ReticleTex},
  1055.         {W3D_ATO_FORMAT,    W3D_A4R4G4B4},
  1056.         {W3D_ATO_WIDTH,     64},
  1057.         {W3D_ATO_HEIGHT,    64}
  1058.     };
  1059.     int ifferror, x, y, i, j;
  1060.     unsigned char a, b;
  1061.     UWORD *to;
  1062.     ULONG CError;
  1063.  
  1064.     if (wreticle == NULL) {     // create and load bitmao
  1065.         wreticle = gr_create_bitmap(64, 64);
  1066.         ifferror = iff_read_into_bitmap("reticle.iff", wreticle, NULL);
  1067.         if (ifferror != IFF_NO_ERROR) {
  1068.             printf("Error: Can`t get reticle bitmap: %d\n", ifferror);
  1069.             WARP_wreticle = 0;
  1070.             return;
  1071.         }
  1072.     }
  1073.  
  1074.     to = &ReticleTex[0];
  1075.     for (i = 0; i < 64*64; i++) {   //  create texture from bitmap
  1076.         a = wreticle->bm_data[i];
  1077.         if (a <= 11) *to++ = rcol[a];
  1078.         else         *to++ = 0x0000;
  1079.     }
  1080.  
  1081.     WARP_Reticle = W3D_AllocTexObj(WARP_Context, &CError, ATO_Tags);
  1082.     if (CError != W3D_SUCCESS) {
  1083.         printf("Warning: W3D_AllocTexObj failed for reticle texture:");
  1084.         WARP_Error(CError);
  1085.         WARP_wreticle = 0;
  1086.         return;
  1087.     }
  1088.     W3D_SetWrapMode(WARP_Context, WARP_Reticle, W3D_REPEAT, W3D_REPEAT, NULL);
  1089.     W3D_SetTexEnv(WARP_Context, WARP_Reticle, W3D_MODULATE, NULL);
  1090.     W3D_SetFilter(WARP_Context, WARP_Reticle, W3D_LINEAR, W3D_LINEAR);
  1091. }
  1092.  
  1093.  
  1094.  
  1095. /*
  1096. **  WARP_show_reticle
  1097. **  Draw the Warp3D MEGA reticle
  1098. */
  1099.  
  1100. void WARP_show_reticle(void)
  1101. {
  1102.     int laser_ready = allowed_to_fire_laser();
  1103.     int i, j;
  1104.  
  1105.     if (WARP_wreticle == 0) return;
  1106.  
  1107.     rtris.tex = WARP_Reticle;
  1108.     W3D_LockHardware(WARP_Context);
  1109.     W3D_DrawTriFan(WARP_Context, &rtris);
  1110.     W3D_UnLockHardware(WARP_Context);
  1111.  
  1112. }
  1113.  
  1114.  
  1115. /*
  1116. **  WARP_AddLight
  1117. **  Add light component
  1118. */
  1119. W3D_Float WARP_AddLight(W3D_Float c, int add)
  1120. {
  1121.     W3D_Float b, a = add/256.0;
  1122.     b = c + a * WARP_MFactor;
  1123.     if (b > 1.0) b = 1.0;
  1124.     return b;
  1125. }
  1126.  
  1127.  
  1128. /*
  1129. ** WARP_select_mode
  1130. ** Select screen modes
  1131. */
  1132. int WARP_select_mode(void)
  1133. {
  1134.     Mode320x200 = W3D_RequestModeTags(
  1135.         W3D_SMR_TYPE,       W3D_DRIVER_3DHW,
  1136.         W3D_SMR_SIZEFILTER, TRUE,
  1137.         W3D_SMR_DESTFMT,    W3D_FMT_R5G5B5,
  1138.         ASLSM_TitleText,    (ULONG)"Select Screen mode for 320x200 Screens",
  1139.         ASLSM_MinWidth,     320,
  1140.         ASLSM_MaxWidth,     321,
  1141.         ASLSM_MinHeight,    200,
  1142.         ASLSM_MaxHeight,    256,
  1143.     TAG_DONE);
  1144.  
  1145.     if (Mode320x200 == INVALID_ID)  return 0;
  1146.  
  1147.     Mode320x400 = W3D_RequestModeTags(
  1148.         W3D_SMR_TYPE,       W3D_DRIVER_3DHW,
  1149.         W3D_SMR_SIZEFILTER, TRUE,
  1150.         W3D_SMR_DESTFMT,    W3D_FMT_R5G5B5,
  1151.         ASLSM_TitleText,    (ULONG)"Select Screen mode for 320x400 Screens",
  1152.         ASLSM_MinWidth,     320,
  1153.         ASLSM_MaxWidth,     640,
  1154.         ASLSM_MinHeight,    400,
  1155.         ASLSM_MaxHeight,    512,
  1156.     TAG_DONE);
  1157.  
  1158.     Mode640x480 = W3D_RequestModeTags(
  1159.         W3D_SMR_TYPE,       W3D_DRIVER_3DHW,
  1160.         W3D_SMR_SIZEFILTER, TRUE,
  1161.         W3D_SMR_DESTFMT,    W3D_FMT_R5G5B5,
  1162.         ASLSM_TitleText,    (ULONG)"Select Screen mode for 640x480 Screens",
  1163.         ASLSM_MinWidth,     640,
  1164.         ASLSM_MaxWidth,     641,
  1165.         ASLSM_MinHeight,    480,
  1166.         ASLSM_MaxHeight,    512,
  1167.     TAG_DONE);
  1168.  
  1169.     if (Mode640x480 == INVALID_ID)  return 0;
  1170.  
  1171.     Mode800x600 = W3D_RequestModeTags(
  1172.         W3D_SMR_TYPE,       W3D_DRIVER_3DHW,
  1173.         W3D_SMR_SIZEFILTER, TRUE,
  1174.         W3D_SMR_DESTFMT,    W3D_FMT_R5G5B5,
  1175.         ASLSM_TitleText,    (ULONG)"Select Screen mode for 800x600 Screens",
  1176.         ASLSM_MinWidth,     800,
  1177.         ASLSM_MaxWidth,     801,
  1178.         ASLSM_MinHeight,    600,
  1179.         ASLSM_MaxHeight,    601,
  1180.     TAG_DONE);
  1181.  
  1182.     if (Mode800x600 == INVALID_ID)  return 0;
  1183.  
  1184.     return 1;
  1185. }
  1186.  
  1187.  
  1188. /*
  1189. **  WARP_set_mode
  1190. **  Warp3D version of gr_set_mode
  1191. */
  1192. int WARP_set_mode(int mode)
  1193. {
  1194.     int w, h, r, x, y;
  1195.     ULONG sa_error;
  1196.     int real_mode = mode;
  1197.     char *smode;
  1198.     int i;
  1199.     long cmode;
  1200.     ulong adr;
  1201.     int direct = 0;
  1202.     struct DisplayInfo di_info;
  1203.     DisplayInfoHandle di_handle;
  1204.     struct Screen *scr2=NULL;
  1205.     struct Window *win2=NULL;
  1206.  
  1207.     if (gr_keep_resolution && scr) {
  1208.  
  1209.         switch (mode) {
  1210.             case SM_ORIGINAL:
  1211.                 return 0;
  1212.             case SM_320x200x8:
  1213.             case SM_320x200C:
  1214.             case SM_320x200x8UL:
  1215.                 w = 320;
  1216.                 h = 200;
  1217.                 smode = gr_sc_small;
  1218.                 x = 0;
  1219.                 y = 0;
  1220.                 cmode = Mode320x200;
  1221.                 break;
  1222.             case SM_320x400U:
  1223.                 w = 320;
  1224.                 h = 400;
  1225.                 smode = gr_sc_medium;
  1226.                 x = 0;
  1227.                 y = 0;
  1228.                 if (Mode320x400 == INVALID_ID) {
  1229.                     cmode = Mode640x480;
  1230.                     w = 640;
  1231.                     h = 480;
  1232.                 } else {
  1233.                     cmode = Mode320x400;
  1234.                 }
  1235.                 break;
  1236.  
  1237.             case SM_320x200x16:
  1238.                 exit(1);
  1239.                 break;
  1240.             case SM_800x600V:
  1241.                 w = 800;
  1242.                 h = 600;
  1243.                 x = 0;
  1244.                 y = 0;
  1245.                 cmode = Mode800x600;
  1246.                 break;
  1247.  
  1248.             default:
  1249.                 printf("Warning: Unknown screen mode. Opening large default\n");
  1250.             case SM_640x480V:
  1251.                 w = 640;
  1252.                 h = 480;
  1253.                 smode = gr_sc_large;
  1254.                 x = 0;
  1255.                 y = 0;
  1256.                 cmode = Mode640x480;
  1257.                 break;
  1258.         }
  1259.  
  1260.         gr_palette_clear();
  1261.  
  1262.         grd_curscreen->sc_w = w;
  1263.         grd_curscreen->sc_h = h;
  1264.         grd_curscreen->sc_aspect = fixdiv(grd_curscreen->sc_w*3,grd_curscreen->sc_h*4);
  1265.         grd_curscreen->sc_canvas.cv_bitmap.bm_x = 0;
  1266.         grd_curscreen->sc_canvas.cv_bitmap.bm_y = 0;
  1267.         grd_curscreen->sc_canvas.cv_bitmap.bm_type = BM_LINEAR;
  1268.         grd_curscreen->sc_canvas.cv_bitmap.bm_w = w;
  1269.         grd_curscreen->sc_canvas.cv_bitmap.bm_h = h;
  1270.         grd_curscreen->sc_canvas.cv_bitmap.bm_rowsize = w;
  1271.         grd_curscreen->sc_canvas.cv_bitmap.bm_data = (ubyte *)OffscreenBuffer;
  1272.  
  1273.         if (w>600) {
  1274.             wscale = (w+1)/w;
  1275.             hscale = (h+1)/h;
  1276.         } else {
  1277.             wscale = 1.0;
  1278.             hscale = 1.0;
  1279.         }
  1280.  
  1281.         gr_set_current_canvas(NULL);
  1282.  
  1283.         FillPixelArray(win->RPort, 0, 0, win->Width, win->Height, 0);
  1284.         bzero(OffscreenBuffer, VR_render_width*VR_render_height);
  1285.  
  1286.         gr_pixfmt = GetCyberMapAttr(scr->RastPort.BitMap, CYBRMATTR_PIXFMT);
  1287.  
  1288.         WARP_Init(win, cmode);
  1289.  
  1290.         return 0;
  1291.     }
  1292.  
  1293.     if (!PointerData) {
  1294.         PointerData = AllocVec(256, MEMF_CLEAR|MEMF_CHIP);
  1295.         farg = FindArg("-smr");
  1296.         wbmode = 0;
  1297.     }
  1298.  
  1299.     if (Mode320x200 == 0 || Mode320x400 == 0 || Mode640x480 == 0 || Mode800x600 == 0 || farg != 0) {
  1300.         if (farg != 0) {
  1301.             Mode320x200 = 0;
  1302.             Mode320x400 = 0;
  1303.             Mode640x480 = 0;
  1304.             Mode800x600 = 0;
  1305.             farg = 0;
  1306.         }
  1307.         if (WARP_select_mode() == 0) {
  1308.             printf("Error: ScreenMode request canceled, or invalid mode\n");
  1309.             exit(1);
  1310.         }
  1311.     }
  1312.  
  1313.  
  1314.     if (scr) {
  1315.         scr2 = scr;
  1316.         win2 = win;
  1317.         scr=NULL;
  1318.     }
  1319.  
  1320.     if (gr_keep_resolution) mode = VR_screen_mode;
  1321.  
  1322.     switch (mode) {
  1323.         case SM_ORIGINAL:
  1324.             return 0;
  1325.         case SM_320x200x8:
  1326.         case SM_320x200C:
  1327.         case SM_320x200x8UL:
  1328.             w = 320;
  1329.             h = 200;
  1330.             smode = gr_sc_small;
  1331.             x = 0;
  1332.             y = 0;
  1333.             cmode = Mode320x200;
  1334.             break;
  1335.         case SM_320x400U:
  1336.             w = 320;
  1337.             h = 400;
  1338.             smode = gr_sc_medium;
  1339.             x = 0;
  1340.             y = 0;
  1341.             cmode = Mode320x400;
  1342.             break;
  1343.  
  1344.         case SM_320x200x16:
  1345.             exit(1);
  1346.             break;
  1347.         case SM_800x600V:
  1348.             w = 800;
  1349.             h = 600;
  1350.             x = 0;
  1351.             y = 0;
  1352.             cmode = Mode800x600;
  1353.             break;
  1354.  
  1355.         default:
  1356.             printf("Warning: Unknown screen mode. Opening large default\n");
  1357.         case SM_640x480V:
  1358.             w = 640;
  1359.             h = 480;
  1360.             smode = gr_sc_large;
  1361.             x = 0;
  1362.             y = 0;
  1363.             cmode = Mode640x480;
  1364.             break;
  1365.  
  1366.     }
  1367.  
  1368.     ScreenType = 1;
  1369.     depth = 15;
  1370.  
  1371.     if (scr) {
  1372.         scr2 = scr;
  1373.         win2 = win;
  1374.         scr=NULL;
  1375.     }
  1376.  
  1377.     planes = 0;
  1378.  
  1379.     if (!scr) {
  1380.         int f = 2;
  1381.         scr = OpenScreenTags( NULL,
  1382.             SA_Quiet,       TRUE,
  1383.             SA_Left,        0,
  1384.             SA_Top,         0,
  1385.             SA_Width,       w,
  1386.             SA_Height,      h*f,
  1387.             SA_Title,       (ULONG)smode,
  1388.             SA_Depth,       8,
  1389.             SA_Type,        CUSTOMSCREEN,
  1390.             SA_DisplayID,   cmode,
  1391.             SA_ErrorCode,   (ULONG)&sa_error,
  1392.         TAG_DONE);
  1393.  
  1394.         if (!scr) {
  1395.             printf("Can`t open screen: ");
  1396.             switch(sa_error) {
  1397.                 case OSERR_NOMONITOR:
  1398.                     printf("Monitor not available\n"); break;
  1399.                 case OSERR_NOCHIPS:
  1400.                     printf("Custom chips too old\n"); break;
  1401.                 case OSERR_NOMEM:
  1402.                     printf("Could not get enough memory\n"); break;
  1403.                 case OSERR_NOCHIPMEM:
  1404.                     printf("Could not get enough chip memory\n"); break;
  1405.                 case OSERR_PUBNOTUNIQUE:
  1406.                     printf("Public screen name not unique\n"); break;
  1407.                 case OSERR_UNKNOWNMODE:
  1408.                     printf("This mode is unknown\n"); break;
  1409.                 case OSERR_TOODEEP:
  1410.                     printf("Screen too deep to be displayed on this hardware\n"); break;
  1411.                 case OSERR_ATTACHFAIL:
  1412.                     printf("Illegal attachment for screens\n"); break;
  1413.                 default:
  1414.                     printf("Unknown error\n"); break;
  1415.             }
  1416.             exit(1);
  1417.         }
  1418.         if (scr->Width != w || scr->Height != h) {
  1419.             printf("Warning: Screen dimensions do not match requested dimensions\n");
  1420.         }
  1421.         if (win2) {
  1422.             CloseWindow(win2);
  1423.             win2 = NULL;
  1424.         }
  1425.         if (scr2) {
  1426.             CloseScreen(scr2);
  1427.             scr2 = NULL;
  1428.         }
  1429.  
  1430.         win = OpenWindowTags( NULL,
  1431.             WA_Left,        0,
  1432.             WA_Top,         0,
  1433.             WA_Width,       w,
  1434.             WA_Height,      h*2,
  1435.             WA_Flags,       WFLG_BORDERLESS|WFLG_SIMPLE_REFRESH|WFLG_ACTIVATE|WFLG_RMBTRAP|WFLG_REPORTMOUSE,
  1436.             WA_AutoAdjust,  TRUE,
  1437.             WA_IDCMP,       IDCMP_RAWKEY,
  1438.             WA_CustomScreen, (ULONG)scr,
  1439.             WA_SimpleRefresh, TRUE,
  1440.             TAG_DONE);
  1441.  
  1442.         if (!win) {
  1443.             if (scr) {
  1444.                 CloseScreen(scr);
  1445.                 scr = NULL;
  1446.             }
  1447.             if (win2) {
  1448.                 CloseWindow(win2);
  1449.                 win2 = NULL;
  1450.             }
  1451.             if (scr2) {
  1452.                 CloseScreen(scr2);
  1453.                 scr2 = NULL;
  1454.             }
  1455.             Error("Can`t open window (%d,%d)\n", w, h);
  1456.             exit(1);
  1457.         }
  1458.     }
  1459.  
  1460.     if (scr->Width < w || scr->Height < h) {
  1461.         Error("Selected video mode too small\n");
  1462.         exit(0);
  1463.     }
  1464.  
  1465.  
  1466.     if (OffscreenBuffer)
  1467.         FreeVec(OffscreenBuffer);
  1468.  
  1469.     if (gr_keep_resolution == 1)
  1470.         OffscreenBuffer = AllocVec(VR_render_width*VR_render_height, MEMF_CLEAR);
  1471.     else
  1472.         OffscreenBuffer = AllocVec(w*h, MEMF_CLEAR);
  1473.  
  1474.     if (!OffscreenBuffer) {
  1475.             Error("No memory for offscreen buffer\n");
  1476.             exit(0);
  1477.     }
  1478.  
  1479.     OffscreenH = h;
  1480.     OffscreenW = w;
  1481.     OffscreenSize = (h*w)/8;
  1482.  
  1483.     if (compare_buffer) FreeVec(compare_buffer);
  1484.     compare_buffer = 0;
  1485.  
  1486.     if (scr && scr2) {
  1487.         CloseWindow(win2);
  1488.         CloseScreen(scr2);
  1489.     }
  1490.  
  1491.     if (win && wbmode == 0) {
  1492.         SetPointer(win, PointerData, 16, 16, 1, 1);
  1493.     }
  1494.  
  1495.     gr_palette_clear();
  1496.  
  1497.     grd_curscreen->sc_w = w;
  1498.     grd_curscreen->sc_h = h;
  1499.     grd_curscreen->sc_aspect = fixdiv(grd_curscreen->sc_w*3,grd_curscreen->sc_h*4);
  1500.     grd_curscreen->sc_canvas.cv_bitmap.bm_x = 0;
  1501.     grd_curscreen->sc_canvas.cv_bitmap.bm_y = 0;
  1502.     grd_curscreen->sc_canvas.cv_bitmap.bm_type = BM_LINEAR;
  1503.     grd_curscreen->sc_canvas.cv_bitmap.bm_w = w;
  1504.     grd_curscreen->sc_canvas.cv_bitmap.bm_h = h;
  1505.     grd_curscreen->sc_canvas.cv_bitmap.bm_rowsize = w;
  1506.     grd_curscreen->sc_canvas.cv_bitmap.bm_data = (ubyte *)OffscreenBuffer;
  1507.  
  1508.     if (w>600) {
  1509.         wscale = (w+1)/w;
  1510.         hscale = (h+1)/h;
  1511.     } else {
  1512.         wscale = 1.0;
  1513.         hscale = 1.0;
  1514.     }
  1515.  
  1516.     gr_set_current_canvas(NULL);
  1517.  
  1518.     gr_pixfmt = GetCyberMapAttr(scr->RastPort.BitMap, CYBRMATTR_PIXFMT);
  1519.  
  1520.     WARP_Init(win, cmode);
  1521.  
  1522.     return 0;
  1523. }
  1524.  
  1525.  
  1526. /*
  1527. ** WARP_GenFireball
  1528. ** Load and generate fireball texture
  1529. */
  1530. void WARP_GenFireball(void)
  1531. {
  1532. #if 0
  1533.     int i, x, y;
  1534.     char a;
  1535.     ULONG error;
  1536.     FILE *fh = fopen("explosion.p5", "rb");
  1537.     struct TagItem tags [] = {
  1538.         {W3D_ATO_IMAGE,     (ULONG)Fireball},
  1539.         {W3D_ATO_FORMAT,    W3D_A8R8G8B8},
  1540.         {W3D_ATO_WIDTH,     64},
  1541.         {W3D_ATO_HEIGHT,    64},
  1542.         {TAG_DONE,          0}
  1543.  
  1544.  
  1545.     i = fscanf(fh, "P5\n%ld %ld\n255\n", &x, &y);
  1546.  
  1547.     if (i != 2) {
  1548.         printf("Warning: explosion.p5 is no PPM file\n");
  1549.         fclose(fh);
  1550.         return;
  1551.     }
  1552.  
  1553.     if (x != 64 && y != 64) {
  1554.         printf("Warning: explosion.p5 has wrong size\n");
  1555.         fclose(fh);
  1556.         return;
  1557.     }
  1558.  
  1559.     for (i = 0; i < 64*64; i++) {
  1560.         a = fgetc(fh);
  1561.         Fireball[i] = a<<24 | 0xFFFFFF;
  1562.     }
  1563.  
  1564.     fclose(fh);
  1565.  
  1566.     WARP_Fireball = W3D_AllocTexObj( WARP_context, &error, tags);
  1567.  
  1568.     if (error != W3D_SUCCESS) {
  1569.         printf("Warning: Can't create fireball texture: %ld\n", error);
  1570.         WARP_Fireball = NULL;
  1571.         return;
  1572.     }
  1573. #endif
  1574. }
  1575.  
  1576.  
  1577. /*
  1578. ** WARP_DrawFireball
  1579. ** Draw a Warp3D fireball
  1580. */
  1581.  
  1582. void WARP_DrawFireball(object *obj, fix timeleft)
  1583. {
  1584. #if 0
  1585.     g3s_point pnt;
  1586.     W3D_Triangle t1, t2;
  1587.     fix t,w,h;
  1588.  
  1589.     if (g3_rotate_point(&pnt,pos) & CC_BEHIND)
  1590.         return 1;
  1591.  
  1592.     g3_project_point(&pnt);
  1593.  
  1594.     if (pnt.p3_flags & PF_OVERFLOW)
  1595.         return 1;
  1596.  
  1597.     if (checkmuldiv(&t,width,Canv_w2,pnt.p3_z))
  1598.         w = fixmul(t,Matrix_scale.x);
  1599.     else
  1600.         return 1;
  1601.  
  1602.     if (checkmuldiv(&t,height,Canv_h2,pnt.p3_z))
  1603.         h = fixmul(t,Matrix_scale.y);
  1604.     else
  1605.         return 1;
  1606.  
  1607.     blob_vertices[0].x = pnt.p3_sx - w;
  1608.     blob_vertices[0].y = blob_vertices[1].y = pnt.p3_sy - h;
  1609.     blob_vertices[1].x = blob_vertices[2].x = pnt.p3_sx + w;
  1610.     blob_vertices[2].y = pnt.p3_sy + h;
  1611.  
  1612.     t1.tex = WARP_Fireball;
  1613.     t2.tex = WARP_Fireball;
  1614.  
  1615.     t1.v1.x = pnt.p3_sx - w;
  1616.     t1.v1.y = pnt.p3_sy - h;
  1617.     t1.v1.z = 0;
  1618.     t1.v1.w = 12.0 / f2fl(pnt.p3_z);
  1619.     t1.v1.r = t1.v1.g = t1.v1.b = 1.0;
  1620.  
  1621.     t1.v2.x = pnt.p3_sx - w;
  1622.     t1.v2.y = pnt.p3_sy + h;
  1623.     t1.v2.z = 0;
  1624.     t1.v2.w = t1.v1.w;
  1625.     t1.v2.r = t1.v2.g = t1.v2.b = 1.0;
  1626.  
  1627.     t1.v3.x = pnt.p3_sx + w;
  1628.     t1.v3.y = pnt.p3_sy - h;
  1629.     t1.v3.z = 0;
  1630.     t1.v3.w = t1.v1.w;
  1631.     t1.v3.r = t1.v3.g = t1.v3.b = 1.0;
  1632.  
  1633.     t2.v1 = t1.v3;
  1634.     t2.v3 = t1.v2;
  1635.  
  1636.     t2.v2.x = pnt.p3_sx + w;
  1637.     t2.v2.y = pnt.p3_sy + h;
  1638.     t2.v2.z = 0;
  1639.     t2.v2.w = 12.0 / f2fl(pnt.p3_z);
  1640.     t2.v2.r = t2.v2.g = t2.v2.b = 1.0;
  1641.  
  1642.     W3D_DrawTriangle(WARP_Context, &t1);
  1643.     W3D_DrawTriangle(WARP_Context, &t2);
  1644. #endif
  1645. }
  1646.  
  1647. #endif
  1648.